package com.kevin.controller.config.satoken;

import cn.dev33.satoken.context.SaHolder;
import cn.dev33.satoken.context.model.SaRequest;
import cn.dev33.satoken.exception.NotLoginException;
import cn.dev33.satoken.filter.SaServletFilter;
import cn.dev33.satoken.interceptor.SaInterceptor;
import cn.dev33.satoken.router.SaHttpMethod;
import cn.dev33.satoken.router.SaRouter;
import cn.dev33.satoken.stp.StpUtil;
import com.kevin.common.util.IpUtil;
import com.kevin.controller.config.ExceptionTranslator;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import javax.servlet.http.HttpServletRequest;

/**
 * Sa-Token 代码方式进行配置
 *
 * @author kong
 */
@Configuration
@Slf4j
@RequiredArgsConstructor
public class SaTokenConfigure implements WebMvcConfigurer {
    private final IgnoredUrlsConfig ignoredUrlsConfig;
    private final ExceptionTranslator exceptionTranslator;


    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        // 注册 Sa-Token 拦截器，打开注解式鉴权功能
        registry.addInterceptor(new SaInterceptor()).addPathPatterns("/**");
    }

    /**
     * 注册 Sa-Token全局过滤器，解决跨域问题
     */
    @Bean
    public SaServletFilter getSaServletFilter() {
        return new SaServletFilter()
                // 拦截与排除 path
                .addInclude("/**")
                // 全局认证函数
                .setAuth(obj -> {
                    SaRequest request = SaHolder.getRequest();
                    // 解析ip
                    HttpServletRequest servletRequest = (HttpServletRequest) request.getSource();
                    servletRequest.setAttribute("ip", IpUtil.getClientIP(servletRequest));

                    if (request.getMethod().equals(SaHttpMethod.OPTIONS.name())) {
                        // OPTIONS 请求不做检查
                        return;
                    }
                    SaRouter.match("/**").notMatch((param) -> {
                        log.debug("uri:{} method:{}", request.getRequestPath(), request.getMethod());
                        for (String white : ignoredUrlsConfig.getUrls()) {
                            if (SaRouter.isMatch(white, request.getRequestPath())) {
                                return true;
                            }
                        }
                        return false;
                    }).check(StpUtil::checkLogin);
                })
                .setError(e -> exceptionTranslator.handUserExceptionHandler((NotLoginException) e));
    }

}
